package com.xc.xcrpc.server.tcp;

import com.xc.xcrpc.protocol.ProtocolConstant;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.parsetools.RecordParser;


/**
 * 装饰者模式（使用 recordParser 对原有的buffer 处理能力进行增强）
 * @author zqx
 * @since 2024/9/30
 */
public class TcpBufferHandlerWrapper implements Handler<Buffer> {

    /**
     * 解析器，用于解决半包、粘包问题
     */
    private final RecordParser recordParser;

    public TcpBufferHandlerWrapper(Handler<Buffer> bufferHandler) {
        this.recordParser = initRecordParser(bufferHandler);
    }

    /**
     * 初始化解析器
     *
     * @param bufferHandler
     * @return
     *
     * 装饰器函数
     */
    private RecordParser initRecordParser(Handler<Buffer> bufferHandler) {
        //构造 parser
        RecordParser parser = RecordParser.newFixed(ProtocolConstant.MESSAGE_HEADER_LENGTH);
        parser.setOutput(new Handler<io.vertx.core.buffer.Buffer>() {
            //初始化
            int size = -1;
            // 一次完整的读取（头 + 体）
            Buffer resultBuffer = Buffer.buffer();

            @Override
            public void handle(Buffer buffer) {
                if (-1 == size){
                    //读取消息体长度
                    size = buffer.getInt(13);
                    parser.fixedSizeMode(size);
                    // 写入头消息到结果
                    resultBuffer.appendBuffer(buffer);
                }else {
                    //写如体信息到结果
                    resultBuffer.appendBuffer(buffer);
                    System.out.println(resultBuffer.toString());
                    // 已拼接为完整 Buffer，执行处理
                    bufferHandler.handle(resultBuffer);
                    //重置一轮
                    //todo 这里为什么 不改成这样就不行
                    parser.fixedSizeMode(ProtocolConstant.MESSAGE_HEADER_LENGTH);
                    size = -1;
                    resultBuffer = Buffer.buffer();
                }
            }
        });
        return parser;
    }


    @Override
    public void handle(Buffer buffer) {
        recordParser.handle(buffer);
    }
}

/**
 * 装饰器的多种实现方式
 * 基于注解的装饰器
 * 在某些编程语言和框架中，装饰器可以通过注解来实现。例如，在 Python 中，可以使用@语法糖定义装饰器函数，这些装饰器函数可以用来修改被装饰函数的行为，如添加日志记录、权限检查等功能。
 * 在 Java 中，像 Spring 框架也有类似基于注解的 AOP（面向切面编程，从某种意义上是一种装饰器思想的实现），
 * 例如@Aspect注解用于定义切面，@Before、@After等注解用于定义在方法执行前或执行后的增强逻辑。
 * 基于类或函数组合的装饰器（如本示例）
 * 装饰器并不局限于注解的实现方式。在本 Java 示例中，是通过类的组合和函数式接口的使用来实现装饰器模式的。
 * 类的组合：TcpBufferHandlerWrapper类包含了RecordParser实例，通过initRecordParser方法将传入的Handler<Buffer>（被装饰对象）与RecordParser进行组合。
 * RecordParser在这里扮演了增强功能的角色，用于解决半包、粘包问题，而TcpBufferHandlerWrapper整体作为一个装饰器包装了原始的Handler<Buffer>。
 * 函数式接口的使用：在initRecordParser方法中，创建了一个内部匿名类实现Handler<Buffer>接口。
 * 这个内部类在handle方法中实现了特定的逻辑，即先处理消息头获取消息体长度，然后根据消息体长度处理消息体，当完整的消息（头 + 体）被处理后，调用原始的Handler<Buffer>（被装饰对象）进行处理。
 * 这种方式利用了函数式接口的灵活性，在不改变原始Handler<Buffer>接口的情况下，对其功能进行了增强。
 */
